sweep(spec): three self-descriptions re-anchored to a verifiable source of truth (#6242 #4895 #4837) - #7032
Merged
Merged
Conversation
…le source of truth (#7024) Sweep card #7024 — every member is a self-description that stopped being answerable to reality, and each fix re-anchors it to something checkable. #6242 — eight enumerations of the stack-collection set, none answerable to `stack.zod.ts`. New `pnpm check:stack-collection-maps` derives the set from `ObjectStackDefinitionSchema` and reconciles all eight against it in both directions; every deviation is a waiver row carrying its reason, and a stale waiver fails like a stale ledger row. Writing it found a seventh site the hand-audit missed (`APP_CATEGORY_KEYS`) and a divergence between ObjectQL's two copies that neither list shows alone. One code change: `ARTIFACT_FIELD_TO_TYPE` no longer aims the seed collection (`data:`) at the analytics kind (`'dataset'`) — a provably inert entry pointed at the wrong kind. #4837 — the ledger counted "a consumer read site exists" as `live` evidence, which misses producer-less dead keys (`Seed.env`). Adds the `producer` field (resolved like `evidence`, so a call-site claim cannot rot), the criterion in liveness/README.md, and a `--producer-gap` worklist. Six entries re-verified by hand; `seed.env` restamped with both sides cited. #4895 — adds `evidenceScope` (`in-repo` | `cross-repo`), and re-verifies the #4667 retirement batch cross-repo against objectui @c2fd1223: all six keys confirmed, no counter-example. The two surviving tombstone rows carry the scope and the pinned commit. ⛔ Zero acceptance-face changes: authorable-surface.base.json is untouched, and the three drift rows that sit on acceptance faces are recorded as waivers rather than fixed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y3ydyJV9reKBgoez8LAoqY
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 2 package(s): 114 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This was referenced Aug 9, 2026
os-zhuang
marked this pull request as ready for review
August 9, 2026 11:44
This was referenced Aug 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #6242
Fixes #4895
Fixes #4837
Sweep card #7024. All three members completed; none dropped. Shared criterion: each member is a self-description that stopped being answerable to reality, and each fix re-anchors it to something checkable.
Per-item checklist
1. #6242 — eight enumerations of the stack-collection set, none answerable to
stack.zod.ts落点
scripts/check-stack-collection-maps.mjs(new),package.json,.github/workflows/lint.yml,packages/metadata/src/plugin.tsbefore
ObjectStackDefinitionSchemadeclares 32 collections. Seven other places re-enumerate that set by hand (eight enumerations — ObjectQL declares its list twice), and nothing compared any of them to the schema or to each other.ragPipelinesmapped in three sites though no schema declares it;workflows/approvals/roles/profiles/policiesstill iterated by both ObjectQL loops after four ADRs retired them;triggers+workflowsstill legal artifact categories; 19 of 32 collections absent from that enum;ARTIFACT_FIELD_TO_TYPEaimed the seed collection (data:) at the analytics kind name ('dataset').after
pnpm check:stack-collection-mapsderives the set from the schema (top-level keys whose value isz.array(<X>Schema)— mechanical, not a second hand-kept list) and reconciles all eight enumerations against it in both directions. Deviations are legal only as waiver rows carrying a reason, and the list is a ratchet: a waiver that no longer applies fails, like a stale ledger row. An enumeration whose symbol cannot be extracted fails too — an empty list would reconcile against everything. 19 waiver rows landed, each written from the gate's own output. One code change: thedata: 'dataset'entry is removed (provably inert —SeedSchemadeclares nonameand the ingest loop skips nameless items — so no runtime change; not repointed at'seed', which would be new behaviour).Two things the gate found that the hand-audit had not:
APP_CATEGORY_KEYS(packages/runtime/src/app-plugin.ts), carrying three retired kinds;jobs,emailTemplates,tools,skillsare registered from a manifest and not from a nested plugin, so a package shipping them from a nested plugin registers nothing and stamps no ADR-0010 provenance.capabilitieswas added to that copy for exactly this reason (capabilities不在 ObjectQLmetadataArrayKeys注册缝里 —— app 声明的 capability 永远拿不到 registry provenance(#4967 Part 2 拆出) #5870); nobody then asked what else the two lists disagreed about. Recorded with the measurement, not fixed here.2. #4837 — the ledger counted "a consumer read site exists" as
liveevidence落点
packages/spec/scripts/liveness/producer.mts(+ test, new),check-liveness.mts,liveness/README.md,liveness/{seed,job,hook}.jsonbefore A
liveverdict needed only a consumer pointer.Seed.envwasliveon a correct one (filterByEnv) while none of the six call sites building aSeedLoaderRequestpassedenv— so the filter returned its input on its first line anddataset.envwas never read.seed-loader.test.tspassed throughout, because it suppliesconfig.envitself.after The criterion is written in the README: when a property's effect depends on a second input somebody must supply,
liverequires producer-side evidence. Newproducerfield, resolved through the same resolver asevidence(a repo-local path that does not exist fails CI). Absence never fails —check:liveness --producer-gapprints the worklist, and a table says which shapes actually need one. A malformed value fails, same asymmetry asverifiedAt. Six entries re-verified by hand:seed.env(restamped, both sides cited), andjob.timeout+hook.retryPolicy/timeout/onError— the same "read out of an options object built elsewhere" shape, checked and holding (the scheduler threads{retryPolicy, timeout}; the hook binder hands the authored hook to the wrapper). No mass re-grade, and no status flipped.3. #4895 — the #4667 liveness verdicts' cross-repo coverage
落点
producer.mts(evidenceScope),check-liveness.mts,liveness/README.md,liveness/{app,book}.jsonbefore Task 2 (the
homePageIdtombstone prose) landed in #4709. Tasks 1 and 3 were open: the #4667 batch had never been re-verified cross-repo, and no entry could say how wide its last look was.after New
evidenceScope: "in-repo" | "cross-repo", with the README recording the four measured blind-spot cases and the method they force (a negative cross-repo claim must follow the resolved symbol graph through re-export chains — case 4,Notification, proves no specifier match suffices). Task 1 done: all six keys of the #4667 batch re-verified against objectui @c2fd1223.app.homePageIdOuiAppSchema(pin test),AppPreviewignores it (pin test),resolveLandingRoute()documents the removal,RootLandingRedirectroutes onisDefaultapp.areas[].orderAppSchemaRenderer,AppSidebar,UnifiedSidebarall iterate array order and only filterbook.translations/book.groups[].translationsapps/console/src/pages/book-nav.ts) and neitherBooknorBookGroupdeclarestranslationsjob.idJobSchemaonly for client-side metadata-admin validation; no reader ofidtranslation.validationMessagesspec-translations.tstransports the key into the client i18n tree andTranslationPreviewechoes it, but nothing resolves it.translation.zod.ts:320already says exactly this — no correction owedNo counter-example found, which is the honest outcome of task 1 rather than a null result: the two surviving tombstone rows now carry
evidenceScope: cross-repoand the pinned commit. Task 3 is the field itself.⛔ Acceptance face — untouched
packages/spec/authorable-surface.base.jsonis byte-identical (no schema key added, removed or retired).check:authorable-surfacegreen. Three of the drift rows #6242 reports sit on acceptance faces (MetadataCategoryEnumdecides what a published artifact may declare); they are recorded as waivers with their reason rather than fixed, per the sweep's red line.Zero changes outside the member items
git diff --stat origin/main...HEAD, mapped 1:1:scripts/check-stack-collection-maps.mjs(new, +832)package.json(+1),.github/workflows/lint.yml(+12)packages/metadata/src/plugin.ts(+19/−4)data:removal + pin comment).changeset/stack-collection-maps-answerable.md(new)packages/spec/scripts/liveness/producer.mts+.test.ts(new)packages/spec/scripts/liveness/check-liveness.mts(+80)packages/spec/liveness/README.md(+100)packages/spec/liveness/{seed,job,hook}.jsonpackages/spec/liveness/{app,book}.json.changeset/liveness-producer-and-evidence-scope.md(new)Verification record
pnpm exec turbo run build --filter='./packages/*' --filter='./packages/*/*', 70/70. Re-run after mergingorigin/main(the merge brought refactor(types,rest,metadata,analytics): Postgres"x" of relation "y"短语收归 @objectstack/types 一处 #7021, which moves a@objectstack/typesexport; a staledistmadepackages/restfail typecheck until the rebuild — not this diff).--filter '...pkg'(前缀)而非'pkg...'(后缀)—— 方向扫反会让「全绿」毫无意义(#6210 实测) #6218), stated direction: prefix —pnpm --filter '...@objectstack/spec' typecheck(everything that DEPENDS on spec, incl.packages/metadata,packages/objectql,packages/runtime,packages/rest,packages/qa/dogfood, all examples). Green.pnpm --filter @objectstack/spec exec tsc --noEmit— green.pnpm --filter @objectstack/spec exec vitest run scripts/liveness/— 8 files, 143 tests, green (8 new).node scripts/check-stack-collection-maps.mjs --self-test— 11 assertions over synthetic sources, both failure directions (unwaived deviation, stale waiver) driven.check:*gate enumerated from.github/workflows/lint.yml, one by one, not from memory — 46 root gates + 6 spec/lint-filtered (check:generated --reconcile-only,check:skill-docs,check:spec-changes,check:upgrade-guide,check:authorable-surface,check:doc-formula-expressions). All green.node scripts/check-adr-0087-registration.mjs --base origin/main— green (2 non-breaking changesets, no declared-breaking change).authorable-surface.base.json; no generated-products regeneration was triggered, so nothing undercontent/docs/referenceschanged.Coverage limit worth stating
cross-repohere means objectui only. Thecloudruntime is not reachable from an open-source checkout, so no verdict in this sweep claims coverage of it — the README says so where the value is defined, rather than lettingcross-reporead as "everywhere".Generated by Claude Code